/* Anastasia Shuba
   Carolyn Ngo
   EECS22L
   01/14/12 
	Updates: 
	01/16/12 @ 11am - Nastia: fixed double precision on uneven division.
	01/17/12 @ 5:25 = Carolyn: Completed 1.2 Registers using an array. Moved your original operation for single value into my section for 
			  single operation for registers to avoid program conflict that I was experiencing. 
	01/18/12 @ 7:42pm - Carolyn: Fixed the bug with one operation on a single register or integer/float. 
	01/21/12 @ 6:37pm - Nastia: The program is now solid! It passed all my evil tests. And it looks prettier now.

	01/21/12 @ 10:51pm - Carolyn: Created the FileIO sections for saving register values in a binary file. On the very first running of the program
				      no values will be printed out since all of the values are initially zero. Everytime afterwards, the values will always
				      be printed as long as the file they're saved in exists. If the user enters "flush" (case sensitive, must be all lower case)
				      , the register values will all go to zero.   	
			
*/

#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <string.h>
#include <ctype.h>

int manageHistory();
int PrintRegisters();
int RegisterIntoFile();
int ReadPersist();
int SavePersist();


int main()
{

	char *cp;
	char sign[100], sign2[100];
	int numOfArg, isAlpha, regpos;
	int confirmation = 0; /*Confirmation = 0 when program has not exited yet or if it abnormally exits*/
	double acc, num1, num2;
	num1=num2=acc=0;
	cp=NULL;
	double RegisterArray[26] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	numOfArg=isAlpha=regpos=0;
	manageHistory();

	confirmation = ReadPersist(confirmation);

	/*If the program exited abnormally, previous values from the abnormally exited program are flushed*/

	if(confirmation == 0)
	{
		int count;	

		FILE *RegisterFile;
		RegisterFile = fopen("registerhistory.txt","wb");
		for(count = 0; count < 26; count++)
		{
			RegisterArray[count] = 0;
		}
	}

	/*If the program exited normally, the previous values are reused and printed*/

	else if(confirmation == 1)
	{
		PrintRegisters(RegisterArray);

	}

	confirmation = 0;

	while(1)
	{	
		SavePersist(confirmation);
		printf("%g", acc);

		cp=readline(":");
		if(cp !=NULL) 
		{ 
			add_history(cp); 
			write_history("history.txt");
		}

		numOfArg=sscanf(cp, "%s", sign);

		/*For when user types flush for returning all the values of the registers back to zero*/

		if(numOfArg == EOF) 
		{ 
			free(cp);
			confirmation = 1; /*The program normally exits*/
			SavePersist(confirmation);
			break; 
		}
		
		/*If user enters flush, all register values go to zero*/
		else if(strcmp(sign,"flush") == 0)
		{
			int count;

			for(count = 0; count < 26; count++)
			{
			RegisterArray[count] = 0;
			}
			RegisterIntoFile(RegisterArray);
		}

		else if( isdigit(sign[0]) || isdigit(sign[1]) ) /*if the first number is a digit*/
		{

			numOfArg=sscanf(cp, "%lf %s %lf%s", &num1, sign, &num2, sign2);

			/* Positive/Negative numbers being entered */
			if(num2==0 && numOfArg == 1)
			{
				numOfArg=sscanf(cp, "%lf", &num1);
				acc=num1;
			}

			/* For ops with 2 numbers*/
			else if(numOfArg == 3)
			{
				if(strcmp(sign, "+") == 0)
				{
					acc=num1+num2;
				}

				else if(strcmp(sign, "-") == 0)
				{
					acc=num1-num2;
				}

				else if(strcmp(sign, "*") == 0)
				{
					acc=num1*num2;
				}

				else if(strcmp(sign, "/") == 0)
				{
					if(num2==0) printf("Error: cannot divide by zero.\n");	
					else acc=num1/num2;
				}
			}

			else printf("Invalid input.\n");
		}
			
		else /*if the first character is not a digit*/
		{
			numOfArg=sscanf(cp, "%s %s", sign, sign2);

			if( strlen(sign) > 1 ) printf("Invlaid input. Opearators need to be one character long. Please enter spaces between operators and operands.\n");

			else if ( strlen(sign2) > 1 && !(isdigit(sign2[1])) ) printf("Invlaid input. Opearators need to be one character long.\n");

			else if( isalpha(sign[0]) ) /* if it's a sign - register */
			{
				/*Setting the Accumulator equal to the Register -Carolyn*/
				if(strcmp(sign,"A") == 0 || strcmp(sign,"a") == 0)
				{
					if( strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[0] = num1;
					}
					else /*if( !sign2[0] )*/ acc = RegisterArray[0];
				}
			
				else if(strcmp(sign,"B") == 0 || strcmp(sign,"b") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[1] = num1;
					}
					else acc = RegisterArray[1];
				}
			
				else if(strcmp(sign,"C") == 0 || strcmp(sign,"c") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[2] = num1;
					}
					else acc = RegisterArray[2];
				}
			
				else if(strcmp(sign,"D") == 0 || strcmp(sign,"d") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[3] = num1;
					}
					else acc = RegisterArray[3];
				}
			
				else if(strcmp(sign,"E") == 0 || strcmp(sign,"e")  == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[4] = num1;
					}
					else acc = RegisterArray[4];
				}
			
				else if(strcmp(sign,"F") == 0 || strcmp(sign, "f") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[5] = num1;
					}
					else acc = RegisterArray[5];
				}
			
				else if(strcmp(sign,"G") == 0 || strcmp(sign, "g") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[6] = num1;
					}
					else acc = RegisterArray[6];
				}
			
				else if(strcmp(sign,"H") == 0 || strcmp(sign, "h") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[7] = num1;
					}
					else acc = RegisterArray[7];
				}
			
				else if(strcmp(sign, "I") == 0 || strcmp(sign, "i") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[8] = num1;
					}
					else acc = RegisterArray[8];
				}
			
				else if(strcmp(sign,"J") == 0 || strcmp(sign, "j") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[9] = num1;
					}
					else acc = RegisterArray[9];
				}
			
				else if(strcmp(sign,"K") == 0 || strcmp(sign,"k") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[10] = num1;
					}
					else acc = RegisterArray[10];
				}
			
				else if(strcmp(sign, "L") == 0 || strcmp(sign,"l") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[11] = num1;
					}
					else acc = RegisterArray[11];
				}
		
				else if(strcmp(sign, "M") == 0 || strcmp(sign,"m")== 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[12] = num1;
					}
					else acc = RegisterArray[12];
				}

				else if(strcmp(sign, "N") == 0 || strcmp(sign,"n") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[13] = num1;
					}
					else acc = RegisterArray[13];
				}

				else if(strcmp(sign,"O") == 0 || strcmp(sign, "o") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[14] = num1;
					}
					else acc = RegisterArray[14];
				}

				else if(strcmp(sign,"P") == 0 || strcmp(sign,"p") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[15] = num1;
					}
					else acc = RegisterArray[15];
				}

				else if(strcmp(sign,"Q") == 0 || strcmp(sign,"q") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[16] = num1;
					}
					else acc = RegisterArray[16];
				}

				else if(strcmp(sign,"R") == 0 || strcmp(sign,"r") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[17] = num1;
					}
					else acc = RegisterArray[17];
				}
			
				else if(strcmp(sign,"S") == 0 || strcmp(sign,"s") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[18] = num1;
					}
					else acc = RegisterArray[18];
				}

				else if(strcmp(sign,"T") == 0 || strcmp(sign,"t") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[19] = num1;
					}
					else acc = RegisterArray[19];
				}
		
				else if(strcmp(sign,"U") == 0 || strcmp(sign,"u") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[20] = num1;
					}
					else acc = RegisterArray[20];
				}
		
				else if(strcmp(sign,"V") == 0 || strcmp(sign,"v") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[21] = num1;
					}
					else acc = RegisterArray[21];
				}
			
				else if(strcmp(sign,"W") == 0 || strcmp(sign,"w") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[22] = num1;
					}
					else acc = RegisterArray[22];
				}
		
				else if(strcmp(sign,"X") == 0 || strcmp(sign, "x") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[23] = num1;
					}
					else acc = RegisterArray[23];
				}
		
				else if(strcmp(sign,"Y") == 0 || strcmp(sign,"y") ==0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[24] = num1;
					}
					else acc = RegisterArray[24];
				}
		
				else if(strcmp(sign,"Z") == 0 || strcmp(sign,"z") == 0)
				{
					if(strcmp(sign2, "=") == 0)
					{
						numOfArg=sscanf(cp, "%s %s %lf", sign, sign2, &num1);
						RegisterArray[25] = num1;
					}
					else acc = RegisterArray[25];
				}
				else printf("Invalid input.\n");

				RegisterIntoFile(RegisterArray);
			}

			else /* the first char is a sign, an operator */
			{
				if( isalpha(sign2[0]) ) /* if the second operand is a register */
				{
					isAlpha=1;
					if(strcmp(sign2,"A") == 0 || strcmp(sign2,"a") == 0)
					{
						regpos = 0;
					}
					else if(strcmp(sign2,"B") == 0 || strcmp(sign2,"b") == 0)
					{
						regpos = 1;
					}
					else if(strcmp(sign2,"C") == 0 || strcmp(sign2,"c") ==0)
					{
						regpos = 2;
					}
					else if(strcmp(sign2,"D") == 0 || strcmp(sign2,"d") == 0)
					{
						regpos = 3;
					}
					else if(strcmp(sign2,"E") == 0 || strcmp(sign2,"e") == 0)
					{
						regpos = 4;
					}
					else if(strcmp(sign2,"F") == 0 || strcmp(sign2,"f") == 0)
					{
						regpos = 5;
					}
					else if(strcmp(sign2,"G") ==0 || strcmp(sign2,"g") == 0)
					{
						regpos = 6;
					}
					else if(strcmp(sign2,"H") == 0 || strcmp(sign2,"h") == 0)
					{
						regpos = 7;
					}
					else if(strcmp(sign2,"I") == 0 || strcmp(sign2,"i") == 0)
					{
						regpos = 8;
					}
					else if(strcmp(sign2,"J") == 0 || strcmp(sign2,"j") == 0)
					{
						regpos = 9;
					}
					else if(strcmp(sign2,"K") == 0 || strcmp(sign2,"k") == 0)
					{
						regpos = 10;
					}
					else if(strcmp(sign2,"L") == 0 || strcmp(sign2,"l") == 0)
					{
						regpos = 11;
					}
					else if(strcmp(sign2,"M") == 0 || strcmp(sign2,"m") == 0)
					{
						regpos = 12;
					}
					else if(strcmp(sign2,"N") == 0 || strcmp(sign2,"n") == 0)
					{
						regpos = 13;
					}
					else if(strcmp(sign2,"P") == 0 || strcmp(sign2,"p") == 0)
					{
						regpos = 14;
					}
					else if(strcmp(sign2,"O") == 0 || strcmp(sign2,"o") == 0)
					{
						regpos = 15;
					}
					else if(strcmp(sign2,"Q") == 0 || strcmp(sign2,"q") == 0)
					{
						regpos = 16;
					}
					else if(strcmp(sign2,"R") == 0 || strcmp(sign2,"r") == 0)
					{
						regpos = 17;
					}
					else if(strcmp(sign2,"S") == 0 || strcmp(sign2,"s") == 0)
					{
						regpos = 18;
					}
					else if(strcmp(sign2,"T") == 0 || strcmp(sign2,"t") == 0)
					{
						regpos = 19;
					}
					else if(strcmp(sign2,"U") == 0 || strcmp(sign2,"u") == 0)
					{
						regpos = 20;
					}
					else if(strcmp(sign2,"V") == 0 || strcmp(sign2,"v") == 0)
					{
						regpos = 21;
					}
					else if(strcmp(sign2,"W") == 0 || strcmp(sign2,"w") == 0)
					{
						regpos = 22;
					}
					else if(strcmp(sign2,"X") == 0 || strcmp(sign2,"x") == 0)
					{
						regpos = 23;
					}
					else if(strcmp(sign2,"Y") == 0 || strcmp(sign2,"y") == 0)
					{
						regpos = 24;
					}
					else if(strcmp(sign2,"Z") == 0 || strcmp(sign2,"z") == 0)
					{
						regpos = 25;
					}
				}

				if( strcmp(sign, "@")==0 && isAlpha ) 
				{
					RegisterArray[regpos]=acc;
					RegisterIntoFile(RegisterArray);
				}

				else if(strcmp(sign, "+") == 0)
				{
					if(isAlpha) acc=acc+RegisterArray[regpos];

					else if( isdigit(sign2[0]) || isdigit(sign2[1]) )
					{
						numOfArg = sscanf(cp, "%s %lf", sign, &num2);
						acc=acc+num2;
					}
				}

				else if(strcmp(sign, "-") == 0)
				{
					if(isAlpha) acc=acc-RegisterArray[regpos];

					else if( isdigit(sign2[0]) || isdigit(sign2[1]) )
					{
						numOfArg = sscanf(cp, "%s %lf", sign, &num2);
						acc=acc-num2;
					}
				}

				else if(strcmp(sign, "*") == 0)
				{
					if(isAlpha) acc=acc*RegisterArray[regpos];

					else if( isdigit(sign2[0]) || isdigit(sign2[1]) )
					{
						numOfArg = sscanf(cp, "%s %lf", sign, &num2);
						acc=acc*num2;
					}
				}
				else if(strcmp(sign, "/") == 0)
				{	
						
					if(isAlpha) acc=acc/RegisterArray[regpos];

					else if( isdigit(sign2[0]) || isdigit(sign2[1]))
					{
						numOfArg = sscanf(cp, "%s %lf", sign, &num2);
						if(num2==0) printf("Error: cannot divide by zero.\n");
						else acc=acc/num2;
					}
				}
				else printf("Invalid input.\n");
			}
		}
		
		/*for the next loop*/
		num1=num2=numOfArg=0;
		isAlpha=0;
		sign[0]=0;
		sign2[0]=0;
		free(cp);
		
	}
	return 0;
}


/*Putting Register values into a Save File*/

int RegisterIntoFile(double registers[26])
{
	int count = 0;
	FILE *RegisterFile;
	RegisterFile = fopen("registerhistory.txt", "wb");

	if( RegisterFile == 0)
	{
		printf("Could not write registers into file.\n");
		return 1;
	}

	else if( RegisterFile != 0)
	{
		for(count = 0;count < 26; count++)
		{
		fprintf(RegisterFile, "%lf ",registers[count]);
		}
		fclose(RegisterFile);
		
	}	

	return 0;

}

/*Saving confirmation value for abnormal or normal exitting of program*/
int SavePersist(int confirmation)
{
	FILE *Confirm;
	Confirm = fopen("confirmation.txt", "wb");
	if(Confirm == 0)
	{
		printf("Could not save confirmation in file. \n");
	}
	else if(Confirm !=0)
	{
		fprintf(Confirm, "%d", confirmation);
		fclose(Confirm);
	}
	return 0;
}

/*Reading confirmation value*/
int ReadPersist(int confirmation)
{
	FILE *Confirm;
	Confirm = fopen("confirmation.txt", "rb");
	
	if(Confirm == 0)
	{
		Confirm = fopen("confirmation.txt", "wb");
		fprintf(Confirm,"%d", confirmation);
		fclose(Confirm);
	}
	else if(Confirm != 0)
	{
		fscanf(Confirm,"%d", &confirmation);
	}
	
	return confirmation;
}

/*Print Register Values out for user to see*/
int PrintRegisters( double array[26] )
{
	int count;
	double hold;

	FILE *RegisterFile;
	RegisterFile = fopen("registerhistory.txt", "rb");

	/*If file does not exist, load current values into file*/
	/*PLEASE NOTE: Does not print values if file is being created for the first time*/
	if(RegisterFile == 0)
	{
		RegisterFile = fopen("registerhistory.txt", "wb");
		
		for(count = 0; count < 26; count ++)
		{
			fprintf(RegisterFile,"%lf ", array[count]);
		}
		fclose(RegisterFile);
			
	}

	/* out values if file exists*/
	else if(RegisterFile != 0)
	{
		for(count = 0; count <26; count++)
		{
			fscanf(RegisterFile, "%lf ", &hold);
			array[count] = hold;
		}
		fclose(RegisterFile);
	}
	return 0; 

}

int manageHistory()
{
	FILE *History;
	int x;
	History = fopen("history.txt", "r");

	if( History == 0 ) 
	{
		printf("Could not open history of commands.\n");
		return 1;
	}
	
	else if(fgetc(History) == EOF) return 0;
	
	else
	{
		x=read_history("history.txt");
		if(x !=0 )
		{
			 printf("Error while reading history file.\n");
			return 2;
		}
		else return 0;
	}
}


